package com.kelai.service.impl;

import com.google.common.collect.Sets;
import com.kelai.common.IRepository;
import com.kelai.common.InfoPage;
import com.kelai.common.PageInfo;
import com.kelai.common.exception.BreezeeException;
import com.kelai.domain.AccountEntity;
import com.kelai.domain.CustomerEntity;
import com.kelai.domain.RoleEntity;
import com.kelai.domain.VendorEntity;
import com.kelai.repository.IAccountRepository;
import com.kelai.repository.ICustomerRepository;
import com.kelai.repository.IRoleRepository;
import com.kelai.service.IAccountService;
import com.kelai.utils.DynamicSpecifications;
import javafx.util.Callback;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Sort;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.*;

/**
 * 账号服务实现类
 * Created by Silence on 2016/11/26.
 */
@Service("accountService")
public class DefaultAccountService implements IAccountService {

    private final IAccountRepository accountRepository;

    private final IRoleRepository roleRepository;

    private final ICustomerRepository customerRepository;

    private final JdbcTemplate jdbcTemplate;

    private final PlatformTransactionManager transactionManager;

    @Autowired
    public DefaultAccountService(IAccountRepository accountRepository, JdbcTemplate jdbcTemplate, PlatformTransactionManager transactionManager, IRoleRepository roleRepository, ICustomerRepository customerRepository) {
        this.accountRepository = accountRepository;
        this.jdbcTemplate = jdbcTemplate;
        this.transactionManager = transactionManager;
        this.roleRepository = roleRepository;
        this.customerRepository = customerRepository;
    }

    @Override
    public IRepository<AccountEntity> getRepository() {
        return accountRepository;
    }

    @Override
    public AccountEntity saveInfo(AccountEntity accountEntity, Callback<AccountEntity, Object>... callback) throws BreezeeException {
        AccountEntity result = new AccountEntity();
        if(StringUtils.isEmpty(accountEntity.getId())){//新增
            result = getRepository().saveEntity(accountEntity, callback);
        }else{//修改
            result = getRepository().saveEntity(accountEntity, callback);
            if (accountEntity.getCustomer() != null) {
                updateAcnCusRel(result.getId(),accountEntity.getCustomer().getId());
            }
            if (accountEntity.getVendor() != null) {
                updateAcnVenRel(result.getId(),accountEntity.getVendor().getId());
            }
        }

        return result;
    }

    @Override
    public InfoPage<AccountEntity> pageAll(AccountEntity t) throws BreezeeException {
        PageInfo pageInfo = new PageInfo(t.getProperties());
        if (t.getProperties().get("_sort") != null) {
            pageInfo.setSort((Sort) t.getProperties().get("_sort"));
        } else {
            pageInfo.setSort(new Sort(Sort.Direction.ASC, "rowNum", "id"));
        }

        if (t.getProperties().get("_roleId") != null) {
            RoleEntity entity = roleRepository.findOne(t.getProperties().get("_roleId").toString());
            t.getProperties().put("roles_of", entity);
        }
        if (t.getProperties().get("_not_roleId") != null) {
            RoleEntity entity = roleRepository.findOne(t.getProperties().get("_not_roleId").toString());
            t.getProperties().put("roles_of_not", entity);
        }
        Page<AccountEntity> page = getRepository().findAll(DynamicSpecifications.createSpecification(t.getProperties()), pageInfo);
        return new InfoPage<AccountEntity>(page.getContent(), page.getTotalElements());
    }

    @Override
    public List<AccountEntity> listAll(AccountEntity t) throws BreezeeException {
        PageInfo pageInfo = new PageInfo(t.getProperties());
        if (t.getProperties().get("_sort") != null) {
            pageInfo.setSort((Sort) t.getProperties().get("_sort"));
        } else {
            pageInfo.setSort(new Sort(Sort.Direction.ASC, "rowNum", "id"));
        }

        if (t.getProperties().get("_roleId") != null) {
            RoleEntity entity = roleRepository.findOne(t.getProperties().get("_roleId").toString());
            t.getProperties().put("roles_of", entity);
        }
        if (t.getProperties().get("_not_roleId") != null) {
            RoleEntity entity = roleRepository.findOne(t.getProperties().get("_not_roleId").toString());
            t.getProperties().put("roles_of_not", entity);
        }

        return getRepository().findAll(DynamicSpecifications.createSpecification(t.getProperties()));
    }

    @Override
    public void saveAccounts(VendorEntity ve) {
        String delSql = "delete from R_VEN_ACN where VEN_ID='" + ve.getId() + "'";
        String delSqlActAll = "delete from R_VEN_ACN where ACN_ID = ?";
        String delActAll = "delete from R_CUS_ACN where ACN_ID = ?";
        String insertSql = "insert into R_VEN_ACN (VEN_ID,ACN_ID) values(?,?)";
        List<Object[]> l = new ArrayList<>();
        List<Object[]> ll = new ArrayList<>();
        if (ve.getAccounts() != null) {
            ve.getAccounts().forEach(a -> {
                ll.add(new Object[]{a.getId()});
                l.add(new Object[]{ve.getId(), a.getId()});
            });
        }
        executeSql(delSql, delSqlActAll, delActAll, insertSql, l, ll);
    }
    @Override
    public void saveAccounts(CustomerEntity ce) {
        String delSql = "delete from R_CUS_ACN where CUS_ID='" + ce.getId() + "'";
        String delSqlActAll = "delete from R_CUS_ACN where ACN_ID = ?";
        String delActAll = "delete from R_VEN_ACN where ACN_ID = ?";
        String insertSql = "insert into R_CUS_ACN (CUS_ID,ACN_ID) values(?,?)";
        List<Object[]> l = new ArrayList<>();
        List<Object[]> ll = new ArrayList<>();
        if (ce.getAccounts() != null) {
            ce.getAccounts().forEach(a -> {
                ll.add(new Object[]{a.getId()});
                l.add(new Object[]{ce.getId(), a.getId()});
            });
        }
        executeSql(delSql, delSqlActAll, delActAll, insertSql, l, ll);
    }

    /*private void saveAcnCusRel(String acnId,String cusId) {
        String insertSql = "insert into R_CUS_ACN (CUS_ID,ACN_ID) values(?,?)";
        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.execute(status -> {
            jdbcTemplate.update(insertSql,new Object[]{cusId, acnId});
            return null;
        });
    }*/
    private void updateAcnCusRel(String acnId,String cusId) {
        String delCusRel = "delete from R_CUS_ACN where ACN_ID = '"+acnId+"'";
        String delVenRel = "delete from R_VEN_ACN where ACN_ID = '"+acnId+"'";
        String insertSql = "insert into R_CUS_ACN (CUS_ID,ACN_ID) values(?,?)";

        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.execute(status -> {
            jdbcTemplate.update(delCusRel);
            jdbcTemplate.update(delVenRel);
            jdbcTemplate.update(insertSql,new Object[]{cusId, acnId});
            return null;
        });
    }

    /*private void saveAcnVenRel(String acnId,String venId) {
        String insertSql = "insert into R_VEN_ACN (VEN_ID,ACN_ID) values(?,?)";
        jdbcTemplate.update(insertSql,new Object[]{venId, acnId});
    }*/
    private void updateAcnVenRel(String acnId,String venId) {
        String delVenRel = "delete from R_VEN_ACN where ACN_ID = '"+acnId+"'";
        String delCusRel = "delete from R_CUS_ACN where ACN_ID = '"+acnId+"'";
        String insertSql = "insert into R_VEN_ACN (VEN_ID,ACN_ID) values(?,?)";

        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.execute(status -> {
            jdbcTemplate.update(delVenRel);
            jdbcTemplate.update(delCusRel);
            jdbcTemplate.update(insertSql,new Object[]{venId, acnId});
            return null;
        });
    }

    private void saveAcnRoleRel(String acnId,String roleId) {
        String insertSql = "insert into R_ROLE_ACN (ROLE_ID,ACN_ID) values(?,?)";

        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.execute(status -> {
            jdbcTemplate.update(insertSql,new Object[]{roleId, acnId});
            return null;
        });
    }

    @Override
    public void saveAccounts(RoleEntity role) {
        String delSql = "delete from R_ROLE_ACN where ROLE_ID='" + role.getId() + "'";
        String insertSql = "insert into R_ROLE_ACN (ROLE_ID,ACN_ID) values(?,?)";
        List<Object[]> l = new ArrayList<>();
        if (role.getAccounts() != null) {
            role.getAccounts().forEach(a -> {
                l.add(new Object[]{role.getId(), a.getId()});
            });
        }
        jdbcTemplate.update(delSql);
        if (l.size() > 0)
            jdbcTemplate.batchUpdate(insertSql, l);
    }

    @Override
    public void saveRefRoleAcn(String roleId, String acnId) {
        String delSql = "delete from R_ROLE_ACN where ROLE_ID='" + roleId + "' and ACN_ID='"+acnId+"'";
        String insertSql = "insert into R_ROLE_ACN (ROLE_ID,ACN_ID) values(?,?)";
        List<Object[]> l = new ArrayList<>();
        l.add(new Object[]{roleId, acnId});
        jdbcTemplate.update(delSql);
        if (l.size() > 0)
            jdbcTemplate.batchUpdate(insertSql, l);
    }

    @Override
    public Set<CustomerEntity> findMyShop(String accountId) {
        AccountEntity account = accountRepository.findOne(accountId);
        Set<CustomerEntity> set = new HashSet<>();
        if (account.getType() == 2) {
            CustomerEntity ce = account.getCustomer();
            if (ce != null)
                ce.findDeepChildren(set);
        } else if (account.getType() == 3) {
            VendorEntity vendor = account.getVendor();
            if (vendor != null && vendor.getCustomers() != null) {
                vendor.getCustomers().forEach(a -> {
                    a.getCustomer().findDeepChildren(set);
                });
            }
        } else {
            List<CustomerEntity> l = customerRepository.findTopCustomer();
            if (l != null)
                l.forEach(a -> {
                    a.findDeepChildren(set);
                });
        }
        return set;
    }

    @Override
    public void saveAccountDirect(AccountEntity ae) {
        getRepository().saveEntity(ae);
    }

    private void executeSql(String sql1, String sql2, String sql3, String sql4, List<Object[]> l, List<Object[]> ll) {
        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.execute(status -> {
            jdbcTemplate.update(sql1);
            if (ll.size() > 0) {
                jdbcTemplate.batchUpdate(sql2, ll);
                jdbcTemplate.batchUpdate(sql3, ll);
            }
            if (l.size() > 0)
                jdbcTemplate.batchUpdate(sql4, l);
            return null;
        });
    }
}
